package com.mjk.common.base.work;


import com.mjk.common.base.error.BizException;
import com.mjk.common.base.model.BaseEntity;
import com.mjk.common.base.model.SystemDate;
import com.mjk.common.base.work.annotation.BeeWork;
import com.mjk.common.base.work.annotation.BeeWorkProxy;
import com.mjk.common.tools.excel.annotation.ExportFiled;
import com.mjk.common.tools.lambada.LambdaMeta;
import com.mjk.common.tools.lambada.LambdaReflectionUtil;
import com.mjk.common.tools.lambada.LambdaUtils;
import com.mjk.common.tools.lambada.function.BeeFunction;
import com.mjk.common.tools.logger.BizLogger;
import com.mjk.common.util.*;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.core.annotation.AnnotatedElementUtils;

import java.lang.reflect.Field;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap;

public class BaseWork {
	/**
	 * 默认删除标志 0 表示未删除
	 */
	public static final String DEFAULT_DEL_FLAG = "0";
	/**
	 * 删除标志，已删除
	 */
	public static final String DEL_FLAG = "1";
	/**
	 * 不能为空
	 */
	private static final String IS_NULL = "不能为空";

	 /**
     * 获取当前时间
     *
      */
    public Timestamp getNowTime() {
        return new SystemDate(new Date().getTime());
    }
	/**
	 * 非空判断
     */
	public void needParams(Object dto,String... strs){
        BeeWork work = this.getClass().getAnnotation(BeeWork.class);
        if (null != work && work.isDynamic()) {//是否开启动态参数
            needParamsWithDynamic(dto, strs);
        } else {//没有开启动态参数
            needParamsNoDynamic(dto, strs);
        }
    }

    /**
     * 使用lamadba表达式判断非空
     */
    @SafeVarargs
    public final <T> void needParams(Object o, BeeFunction<T, ?>... funs) {
        for (BeeFunction<T, ?> item : funs) {
            LambdaMeta meta = LambdaUtils.extract(item);
            Object result = LambdaReflectionUtil.invoke(o, meta.getImplMethodName(), null);
            String fieldName = LambdaUtils.methodToProperty(meta.getImplMethodName());
            if (ObjectUtils.isEmpty(result)) {
                throw new BizException(-1, fieldName + IS_NULL);
            }
        }
    }

    /**
     * 获取参数名称
     *
     * @return
     */
    private void needParamsWithDynamic(Object dto, String... strs) {
        String fix = "$cglib_prop_";
        for (String str : strs) {
            if (ObjectUtils.isEmpty(ReflectionUtils.getFieldValue(dto, fix + str))) {
                throw new BizException(-1, str + IS_NULL);
            }
        }
        needParamsNoDynamic(dto, strs);
    }

    private void needParamsNoDynamic(Object dto, String... strs) {
        for (String str : strs) {
            if (ObjectUtils.isEmpty(ReflectionUtils.getFieldValue(dto, str))) {
                Field f = ReflectionUtils.getField(dto.getClass(), str);
                ExportFiled filed = null;
                if (f != null) {
                    filed = AnnotatedElementUtils.getMergedAnnotation(f, ExportFiled.class);
                }
                if (null != filed) {
                    if (ObjectUtils.isEmpty(filed.comment())) {
                        throw new BizException(-1, str + IS_NULL);
                    } else {
                        throw new BizException(-1, filed.comment() + IS_NULL);
                    }
                } else {
                    throw new BizException(-1, str + IS_NULL);
                }
            }
        }
    }
	/**
	 *
     */
	public Object getVaule(Object o,String fileName){
		Object value = ReflectionUtils.getFieldValue(o,fileName);
		if(ObjectUtils.isEmpty(value)){
			String fix = "$cglib_prop_";
			value = ReflectionUtils.getFieldValue(o,fix+fileName);
		}
		return value;
	}
	/**
	 * 分页判断
     */
	public boolean isPage(Object dto){
        return ObjectUtils.isNotEmpty(ReflectionUtils.getFieldValue(dto, "pageSize"))
                && ObjectUtils.isNotEmpty(ReflectionUtils.getFieldValue(dto, "pageStart"));
    }
	/**
	 * 获取树形结构
     */
    public <K extends BaseEntity> List<K> getTreeList(List<K> meuns, String parentId, String childName, String parentName, String subName, boolean isSub) {
        return TreeUtils.list2Tree(meuns, parentId, childName, parentName, subName, isSub);
	}
	
	public Map<String,Object> getWorkMapping(ContextRefreshedEvent event){
		Map<String,Object> workMapping = new ConcurrentHashMap<>();
		Map<String,Object> beas = event.getApplicationContext().getBeansWithAnnotation(BeeWork.class);
		for(Entry<String,Object> entry : beas.entrySet()){
			//此处有可能回出现代理对象，如果是代理对象要转为非代理对象
			Object target = AopTargetUtils.getTarget(entry.getValue());
			BeeWork work = null;
			if (target != null) {
				work = target.getClass().getAnnotation(BeeWork.class);
			}
			if (work != null) {
				workMapping.put(work.work().toUpperCase(), entry.getValue());
			}
		}
		//获取代理对象
		Map<String,Object> proxys = event.getApplicationContext().getBeansWithAnnotation(BeeWorkProxy.class);
		for(Entry<String,Object> entry : proxys.entrySet()){
			Object target = AopTargetUtils.getTarget(entry.getValue());
			Class<?> superClazz = null;
			if (target != null) {
				superClazz = target.getClass().getSuperclass();
			}
			if(null!=superClazz && !Object.class.equals(superClazz)){
				BeeWork work = superClazz.getAnnotation(BeeWork.class);
				if(null != work)
					workMapping.put(work.work().toUpperCase(), (entry.getValue()));
			}
		}	
		return workMapping;
	}
}